#include <WiFi.h>
#include <U8g2_for_Adafruit_GFX.h>  //甘草修改的u8g2图像库
#include <GxEPD2_BW.h>
#include <Adafruit_GFX.h>  //图像库
#include <EEPROM.h>
#include <string>
#include <esp_sleep.h>
extern void clockloop(int,int);
extern void alarmget();
//以上是库文件
//以上是程序文件
#define pi 3.14159265
#include <string>
using std::string;
//extern tmElements_t ;
extern DateTime nowtime;
;
extern Alarmt alTime;

extern int theme;
extern int Tyear;
extern int Tmon;
extern int Tday;
extern int Thour;
extern int Tmin;
extern int Tsec;
extern const char* today1;
extern char* dayOfWeekName[];
extern void roundclockloop();
String HexToBin(char strHex) {//16转2进制
  if (strHex == '0') {
    String a = "0000";
    return a;
  } else if (strHex == '1') {
    String a = "0001";
    return a;
  } else if (strHex == '2') {
    String a = "0010";
    return a;
  } else if (strHex == '3') {
    String a = "0011";
    return a;
  } else if (strHex == '4') {
    String a = "0100";
    return a;
  } else if (strHex == '5') {
    String a = "0101";
    return a;
  } else if (strHex == '6') {
    String a = "0110";
    return a;
  } else if (strHex == '7') {
    String a = "0111";
    return a;
  } else if (strHex == '8') {
    String a = "1000";
    return a;
  } else if (strHex == '9') {
    String a = "1001";
    return a;
  } else if (strHex == 'A') {
    String a = "1010";
    return a;
  } else if (strHex == 'B') {
    String a = "1011";
    return a;
  } else if (strHex == 'C') {
    String a = "1100";
    return a;
  } else if (strHex == 'D') {
    String a = "1101";
    return a;
  } else if (strHex == 'E') {
    String a = "1110";
    return a;
  } else if (strHex == 'F') {
    String a = "1111";
    return a;
  }
}
bool tapcheck(int bn) {//按键检测
  if (bn == 1) {
    if (digitalRead(button1) == bt1click) return true;
    else return false;
  }
  if (bn == 2) {
    if (digitalRead(button2) == bt2click) return true;
    else return false;
  }
  if (bn == 3) {
    if (digitalRead(button3) == bt3click) return true;
    else return false;
  }
}
extern void selfclock();//自定义表盘
extern void digitalclock();//数字表盘
extern void roundclock();//指针表盘
extern void isAlarmedcheck();//闹钟触发检测
extern int defaultclock;
int espsleep(int mod = 0) {//轻度睡眠的设定和开启
  pinMode(18, INPUT);
  pinMode(19, INPUT_PULLUP);
  pinMode(9, INPUT_PULLUP);
  pinMode(5, INPUT_PULLUP);
  esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_ALL);
  gpio_wakeup_enable(GPIO_NUM_18, GPIO_INTR_LOW_LEVEL);
  gpio_wakeup_enable(GPIO_NUM_19, GPIO_INTR_LOW_LEVEL);
  gpio_wakeup_enable(GPIO_NUM_9, GPIO_INTR_LOW_LEVEL);
  gpio_wakeup_enable(GPIO_NUM_4, GPIO_INTR_ANYEDGE);
  gpio_wakeup_enable(GPIO_NUM_4, GPIO_INTR_LOW_LEVEL);
  gpio_wakeup_enable(GPIO_NUM_4, GPIO_INTR_NEGEDGE);
  esp_sleep_enable_gpio_wakeup();
  if (mod == 0) {
    esp_sleep_enable_timer_wakeup(1 * 30 * 1000000);
  }


  Serial.println("Sleep");
  esp_light_sleep_start();
  SPI.end();
  Wire.begin(8, 7);
  isAlarmedcheck();

  if (esp_sleep_get_wakeup_cause() == ESP_SLEEP_WAKEUP_TIMER) {//如果被自带的定时器唤醒（esp_sleep_enable_timer_wakeup(1 * 30 * 1000000);）将会进入熄屏显示
    picfile = FFat.open("/[p]pic0.p", FILE_READ);
    picout = picfile.readString();
    // Serial.println("picout");
    // Serial.println(picout);
    // Serial.println("picout");
    picfile.close();
    display.fillScreen(BackC);
    drawScale(picout, 0, 0, 200, 200, 1, 1, false);
    nextPage(10, -1);
    while (1) {
      esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_TIMER);
      gpio_wakeup_enable(GPIO_NUM_18, GPIO_INTR_LOW_LEVEL);
      gpio_wakeup_enable(GPIO_NUM_19, GPIO_INTR_LOW_LEVEL);
      gpio_wakeup_enable(GPIO_NUM_9, GPIO_INTR_LOW_LEVEL);
      gpio_wakeup_enable(GPIO_NUM_4, GPIO_INTR_ANYEDGE);
      gpio_wakeup_enable(GPIO_NUM_4, GPIO_INTR_LOW_LEVEL);
      gpio_wakeup_enable(GPIO_NUM_4, GPIO_INTR_NEGEDGE);
      SPI.end();
      Wire.begin(8, 7);
      mpu_init();
      gpio_wakeup_enable(GPIO_NUM_5, GPIO_INTR_LOW_LEVEL);
      esp_sleep_enable_gpio_wakeup();
      esp_light_sleep_start();
      Wire.end();
      SPI.end();
      Wire.begin(8, 7);
      isAlarmedcheck();
      if (mpu_check() || tapcheck(1) || tapcheck(2) || tapcheck(3)) {//进入熄屏显示后，如果按下任意键或者转腕，将会显示默认表盘
        Wire.end();
        SPI.begin(7, 8, 8, 6);
        break;
      } else {
        continue;
      }
    }
    clockloop(defaultclock,1);//进入熄屏显示后，如果按下任意键或者转腕，将会显示默认表盘
    // switch (defaultclock) {
    //   case 0: roundclock(); break;
    //   case 1: digitalclock(); break;
    //   case 2: selfclock(); break;
    //   default: digitalclock(); break;
    // }

    display.firstPage();
    return 1;
  }
  if (tapcheck(1) && tapcheck(2) && tapcheck(3)) ESP.restart();  //模拟rst
  return 0;
}
int buttoncheck(float T) {
  //esp_sleep_enable_timer_wakeup(T * 60 * 1000000);
  return espsleep();
}
extern String Batterystr;

void centerx(String& text1, int y, int mod = 1, int x0 = 0, int dx = 200, char* MOD = "否") {//居中文字显示（文本，显示y坐标，反相模式选择，x0的位置，dx的长度）
  y += yshifting;
  x0 += xshifting;
  const char* text = text1.c_str();
  int text_width = u8g2Fonts.getUTF8Width(text);  //计算文本长度
  switch (mod) {
    case 1://正常显示
      u8g2Fonts.setForegroundColor(FormC);
      u8g2Fonts.setBackgroundColor(BackC);
      break;
    default://反相显示
      u8g2Fonts.setForegroundColor(BackC);
      u8g2Fonts.setBackgroundColor(FormC);
      break;
  }
  int d = (text_width / dx) + 1;
  text_width /= d;
  for (int i = 0; i <= d - 1; i++) {
    const char* dtext = "";
    String s = text;
    s = s.substring(i * (s.length() / d), (1 + i) * (s.length() / d));
    dtext = s.c_str();
    //Serial.println(dtext);
    u8g2Fonts.setCursor(x0 + ((dx - text_width) / 2), ((MOD == "完全居中") ? y - (d * 16 / 2) : y) + 16 * i);  //文本居中
    u8g2Fonts.print(dtext);
  }
}
void centerx(const char* text, int y, int mod = 1, int x0 = 0, int dx = 200, char* MOD = "否") {
  y += yshifting;
  x0 += xshifting;
  int text_width = u8g2Fonts.getUTF8Width(text);  //计算文本长度
  switch (mod) {
    case 1:
      u8g2Fonts.setForegroundColor(FormC);
      u8g2Fonts.setBackgroundColor(BackC);
      break;
    default:
      u8g2Fonts.setForegroundColor(BackC);
      u8g2Fonts.setBackgroundColor(FormC);
      break;
  }
  int d = (text_width / dx) + 1;
  text_width /= d;
  for (int i = 0; i <= d - 1; i++) {
    const char* dtext = "";
    String s = text;
    s = s.substring(i * (s.length() / d), (1 + i) * (s.length() / d));
    dtext = s.c_str();
    //Serial.println(dtext);
    u8g2Fonts.setCursor(x0 + ((dx - text_width) / 2), ((MOD == "完全居中") ? y - (d * 16 / 2) : y) + 16 * i);  //文本居中
    u8g2Fonts.print(dtext);
  }
}
void centerx(char* text, int y, int mod = 1, int x0 = 0, int dx = 200, char* MOD = "否") {
  y += yshifting;
  x0 += xshifting;
  int text_width = u8g2Fonts.getUTF8Width(text);  //计算文本长度
  switch (mod) {
    case 1:
      u8g2Fonts.setForegroundColor(FormC);
      u8g2Fonts.setBackgroundColor(BackC);
      break;
    default:
      u8g2Fonts.setForegroundColor(BackC);
      u8g2Fonts.setBackgroundColor(FormC);
      break;
  }
  int d = (text_width / dx) + 1;
  text_width /= d;
  for (int i = 0; i <= d - 1; i++) {
    const char* dtext = "";
    String s = text;
    s = s.substring(i * (s.length() / d), (1 + i) * (s.length() / d));
    dtext = s.c_str();
    //Serial.println(dtext);

    u8g2Fonts.setCursor(x0 + ((dx - text_width) / 2), ((MOD == "完全居中") ? y - (d * 16 / 2) : y) + 16 * i);  //文本居中
    u8g2Fonts.print(dtext);
  }
}
void centerx_B(char* text, int y, int mod = 1, int x0 = 0, int dx = 296, char* MOD = "否") {
  y += yshifting;
  x0 += xshifting;
  int text_width = u8g2Fonts.getUTF8Width(text);  //计算文本长度
  u8g2Fonts.setForegroundColor(GxEPD_BLACK);
  u8g2Fonts.setBackgroundColor(GxEPD_WHITE);
  int d = (text_width / dx) + 1;
  text_width /= d;
  for (int i = 0; i <= d - 1; i++) {
    const char* dtext = "";
    String s = text;
    s = s.substring(i * (s.length() / d), (1 + i) * (s.length() / d));
    dtext = s.c_str();
    Serial.println(dtext);

    u8g2Fonts.setCursor(x0 + ((dx - text_width) / 2), ((MOD == "完全居中") ? y - (d * 16 / 2) : y) + 16 * i);  //文本居中
    u8g2Fonts.print(dtext);
  }
}
void centerx_B(const char* text, int y, int mod = 1, int x0 = 0, int dx = 296, char* MOD = "否") {
  y += yshifting;
  x0 += xshifting;
  int text_width = u8g2Fonts.getUTF8Width(text);  //计算文本长度
  u8g2Fonts.setForegroundColor(GxEPD_BLACK);
  u8g2Fonts.setBackgroundColor(GxEPD_WHITE);
  int d = (text_width / dx) + 1;
  text_width /= d;
  for (int i = 0; i <= d - 1; i++) {
    const char* dtext = "";
    String s = text;
    s = s.substring(i * (s.length() / d), (1 + i) * (s.length() / d));
    dtext = s.c_str();
    Serial.println(dtext);
    u8g2Fonts.setCursor(x0 + ((dx - text_width) / 2), ((MOD == "完全居中") ? y - (d * 16 / 2) : y) + 16 * i);  //文本居中
    u8g2Fonts.print(dtext);
  }
}
void centerx_B(String& text1, int y, int mod = 1, int x0 = 0, int dx = 296, char* MOD = "否") {
  y += yshifting;
  x0 += xshifting;
  const char* text = text1.c_str();
  int text_width = u8g2Fonts.getUTF8Width(text);  //计算文本长度

  u8g2Fonts.setForegroundColor(GxEPD_BLACK);
  u8g2Fonts.setBackgroundColor(GxEPD_WHITE);

  int d = (text_width / dx) + 1;
  text_width /= d;
  for (int i = 0; i <= d - 1; i++) {
    const char* dtext = "";
    String s = text;
    s = s.substring(i * (s.length() / d), (1 + i) * (s.length() / d));
    dtext = s.c_str();
    Serial.println(dtext);
    u8g2Fonts.setCursor(x0 + ((dx - text_width) / 2), ((MOD == "完全居中") ? y - (d * 16 / 2) : y) + 16 * i);  //文本居中
    u8g2Fonts.print(dtext);
  }
}

void nextPage(int n = 20, int m = 0) /*屏幕刷新（每10次局刷进行一次全局刷新）（集成了电量显示）*/ {
  Wire.end();
  SPI.begin(7, 8, 8, 6);
  n = (theme == 0) ? n / 2 : n;
  if (tick < n) {
    display.setPartialWindow(0, 0, 200, 200);  //设置局部刷新窗口
    //display.setFullWindow();
    ///////////////////////////电量显示
    if (m == 0) {
      display.drawInvertedBitmap(71 + xshifting, 154 + yshifting, battery, 16, 8, FormC);
      Serial.println("batteryok");
      double bfb = getV(Batterystr);
      u8g2Fonts.setFont(u8g2_font_pcsenior_8f);
      //getV(Batterystr);
      //centerx(Batterystr, 160, 1, 92, 40);
      String bbv=String(bv);
      centerx(bbv, 160, 1, 92, 40);
      u8g2Fonts.setFont(chinese_gb2312);
      bfb = (bfb + 6) / 20;
      for (int i = 0; i < (bfb - 1); i++) {
        display.drawFastVLine(73 + i * 2 + xshifting, 156 + yshifting, 4, FormC);
      }
    } else if (m == 1) {
      display.drawInvertedBitmap(24 + xshifting, 169 + yshifting, battery, 16, 8, FormC);
      Serial.println("batteryok");
      double bfb =getV(Batterystr);
      u8g2Fonts.setFont(u8g2_font_pcsenior_8f);
      centerx(Batterystr, 175, 1, 45, 40);
      u8g2Fonts.setFont(chinese_gb2312);
      bfb = (bfb + 6) / 20;
      for (int i = 0; i < (bfb - 1); i++) {
        display.drawFastVLine(26 + i * 2 + xshifting, 171 + yshifting, 4, FormC);
      }
    } else if (m == 2) {
      display.drawInvertedBitmap(71 + xshifting, 60 + yshifting, battery, 16, 8, FormC);
      Serial.println("batteryok");
      double bfb =getV(Batterystr);
      u8g2Fonts.setFont(u8g2_font_pcsenior_8f);
      centerx(Batterystr, 66, 1, 92, 40);
      u8g2Fonts.setFont(chinese_gb2312);
      bfb = (bfb + 6) / 20;
      for (int i = 0; i < (bfb - 1); i++) {
        display.drawFastVLine(73 + i * 2 + xshifting, 62 + yshifting, 4, FormC);
      }
    }
    ///////////////////////////
    display.nextPage();
    tick += 1;
  } else {
    display.setFullWindow();
    display.nextPage();
    tick = 0;
  }
}

//////////////////////////////////////////////缩放绘制string图片的函数
void drawScale(String Pic, int xstart, int ystart, int xmax, int ymax, float xscale = 1, float yscale = 1, bool opposition = false) {
  xstart += xshifting;
  ystart += yshifting;
  int l = Pic.length();
  String pic = "";
  for (int i = 0; i < l; i++) {
    pic += HexToBin(Pic.charAt(i));
  }
  ////////////////////////////////////////////缩放
  int xnew;
  int ynew;
  for (int y = 0; y < ymax; y++) {
    for (int x = 0; x < xmax; x++) {
      xnew = xstart + x * xscale;
      ynew = ystart + y * yscale;
      if (opposition == false) {
        if (pic.charAt(x + y * xmax) == '0') {
          display.drawPixel(xnew, ynew, FormC);
        }
      } else {
        if (pic.charAt(x + y * xmax) == '1') {
          display.drawPixel(xnew, ynew, FormC);
        }
      }
    }
  }
}





//旋转绘制string图片的函数
void drawrotation(String Pic, int xstart, int ystart, int xmax, int ymax, int j, int k, float rotation) {
  xstart += xshifting;
  ystart += yshifting;
  int l = Pic.length();
  String pic = "";
  for (int i = 0; i < l; i++) {
    pic += HexToBin(Pic.charAt(i));
  }
  ////////////////////////////////////////////旋转
  int xnew;
  int ynew;
  for (int y = 0; y < ymax; y++) {
    for (int x = 0; x < xmax; x++) {
      xnew = xstart + (x - j) * cos(rotation) + (y - k) * sin(rotation);
      ynew = ystart + ((x - j) * sin(rotation) - (y - k) * cos(rotation));
      if (pic.charAt(x + y * xmax) == '0') {
        display.drawPixel(xnew, ynew, FormC);
      }
    }
  }
}

//深/浅色模式切换
void themechange() {
  theme = (theme == 1) ? 0 : 1;
}

//前置光开关
void lightmod() {
  pinMode(lightpin, OUTPUT);
  int lightstate = 0;
  const char* state = "off";
  display.fillScreen(GxEPD_BLACK);
  display.fillRoundRect(80, 75 + yshifting, 40, 55, 5, GxEPD_WHITE);
  display.fillRoundRect(85, 108 + yshifting, 30, 18, 5, GxEPD_BLACK);
  u8g2Fonts.setFont(chinese_gb2312);
  u8g2Fonts.setForegroundColor(GxEPD_BLACK);
  u8g2Fonts.setBackgroundColor(GxEPD_WHITE);
  int text_width = u8g2Fonts.getUTF8Width(state);                     //计算文本长度
  u8g2Fonts.setCursor(80 + ((40 - text_width) / 2), 90 + yshifting);  //文本居中
  u8g2Fonts.print(state);
  nextPage();
  while (1) {
    Serial.println("lightmod");
    espsleep();
    if (tapcheck(1) && lightstate == 0) {
      digitalWrite(lightpin, HIGH);
      lightstate = 1;
      display.fillScreen(GxEPD_WHITE);
      display.drawRoundRect(80, 75 + yshifting, 40, 55, 5, GxEPD_BLACK);
      display.drawRoundRect(85, 80 + yshifting, 30, 20, 5, GxEPD_BLACK);
      u8g2Fonts.setFont(chinese_gb2312);
      u8g2Fonts.setForegroundColor(GxEPD_BLACK);
      u8g2Fonts.setBackgroundColor(GxEPD_WHITE);
      state = "on";
      int text_width = u8g2Fonts.getUTF8Width(state);                      //计算文本长度
      u8g2Fonts.setCursor(80 + ((40 - text_width) / 2), 120 + yshifting);  //文本居中
      u8g2Fonts.print(state);
    } else if (tapcheck(1) && lightstate == 1) {
      digitalWrite(lightpin, LOW);
      lightstate = 0;
      display.fillScreen(GxEPD_BLACK);
      display.fillRoundRect(80, 75 + yshifting, 40, 55, 5, GxEPD_WHITE);
      display.fillRoundRect(85, 105 + yshifting, 30, 20, 5, GxEPD_BLACK);
      u8g2Fonts.setFont(chinese_gb2312);
      u8g2Fonts.setForegroundColor(GxEPD_BLACK);
      u8g2Fonts.setBackgroundColor(GxEPD_WHITE);
      state = "off";
      int text_width = u8g2Fonts.getUTF8Width(state);                     //计算文本长度
      u8g2Fonts.setCursor(80 + ((40 - text_width) / 2), 90 + yshifting);  //文本居中
      u8g2Fonts.print(state);
    } else if (tapcheck(2)) return;
    nextPage();
  }
}

extern const char* alarmifo[4];


int homemod = 0;//执行的程序序号，对应下面
String homestring[6]{ "GESTURE", "CLOCK", "SETTING", "LIGHTBULB", "ALARM", "FILES" };//六个子程序
int iconround(int i, int n, int last) {//图标显示的循环（第i个，从i算起的第n个，总个数）
  if (i <= last - n) {
    return i + n;
  } else {
    return i + n - last - 1;
  }
}
extern void mousesetup();//蓝牙鼠标模式
extern void digitalclock();
extern void roundclock();


extern void filedesk();//文件管理主界面
void timepiecedesk();//闹钟/计时器主界面
void homesetup() {//主程序主界面
  //centerx((std::__cxx11::to_string(defaultclock)).c_str(), 20);
  //centerx((std::__cxx11::to_string(alarmchoice)).c_str(), 40);
  //centerx((std::__cxx11::to_string(alTime.aHour) + ":" + std::__cxx11::to_string(alTime.aMin)).c_str(), 60);
// if(alTime.ok)centerx("ok",60);
//   display.nextPage();
  pinMode(18, INPUT);
  pinMode(19, INPUT_PULLUP);
  pinMode(9, INPUT_PULLUP);
  int funselect = 0;
  int last = 5;
  while (1) {
    display.fillScreen(BackC);
    display.drawInvertedBitmap(xshifting, yshifting, home, 200, 200, FormC);
    drawScale(homeicon[iconround(funselect, 0, last)], 31, 87, 64, 64, 0.5, 0.5);
    drawScale(homeicon[iconround(funselect, 1, last)], 68, 43, 64, 64);
    drawScale(homeicon[iconround(funselect, 2, last)], 137, 87, 64, 64, 0.5, 0.5);
    centerx(homestring[iconround(funselect, 1, last)], 150, 1, 50, 100);
    nextPage();
    if (espsleep()) continue;
    Serial.println("wakeup");
    display.firstPage();
    if (tapcheck(1)) {
      delay(200);
      {
        if (tapcheck(1)) funselect = (funselect == 0) ? last : funselect - 1;
        else funselect = (funselect == last) ? 0 : funselect + 1;//不同的funselect对应选择不同的子程序
      }
    }
    if (tapcheck(2) && funselect == 5) {
      //mousesetup();display.firstPage();
      centerx("蓝牙开启", 50);
      nextPage();
      mousesetup();
    }
    if (tapcheck(2) && funselect == 0) {
      //alarmget();
      clockloop(0,0);
      display.firstPage();
    }
    if (tapcheck(2) && funselect == 1) {
      settingdesk();
      display.firstPage();
    }
    if (tapcheck(2) && funselect == 2) {
      lightmod();
      display.firstPage();
    }
    if (tapcheck(2) && funselect == 3) {
      timepiecedesk();
      display.firstPage();
      //alarmget();
    }
    if (tapcheck(2) && funselect == 4) {
      filedesk();
      
      display.firstPage();
    }
    if (tapcheck(3)) {//长按3号按钮进入深度睡眠
      delay(800);
      if (tapcheck(3)) {
        esp_sleep_enable_gpio_wakeup();
        picfile = FFat.open("/[p]pic0.p", FILE_READ);
        picout = picfile.readString();
        picfile.close();
        display.fillScreen(BackC);
        drawScale(picout, 0, 0, 200, 200, 1, 1, false);
        centerx("关机",100);
        nextPage(10, -1);
        esp_deep_sleep_start();
      }
    }
  }
}